<!DOCTYPE html>
<html lang="en">

<!-- Head tag -->
<head><meta name="generator" content="Hexo 3.8.0">

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!--Description-->

    

    
        <meta name="description" content="V4L是 Video for Linux的缩写,它是Linux 内核中关于视频设备的子系统，它为linux 下的视频驱动提供了统一的接口，使得应用程序可以使用统一的API 函数操作不同的视频设备，极大地简化了视频系统的开发和维护。由于早期的 V4L 有很多缺陷，Bill Dirks 等人对其进行了重">
    

    <!--Author-->
    
        <meta name="author" content="Cyrus">
    

    <!--Open Graph Title-->
    
        <meta property="og:title" content="V4L视频采集">
    

    <!--Open Graph Description-->
    
        <meta property="og:description" content="V4L是 Video for Linux的缩写,它是Linux 内核中关于视频设备的子系统，它为linux 下的视频驱动提供了统一的接口，使得应用程序可以使用统一的API 函数操作不同的视频设备，极大地简化了视频系统的开发和维护。由于早期的 V4L 有很多缺陷，Bill Dirks 等人对其进行了重">
    

    <!--Open Graph Site Name-->
        <meta property="og:site_name" content="Cyrus的技术空间">

    <!--Type page-->
    
        <meta property="og:type" content="article">
    

    <!--Page Cover-->
    
    
        <meta property="og:image" content="http://cyrus_huang.gitee.io/bloghttp://www.codeblocq.com/assets/projects/hexo-theme-clean-blog/img/home-bg.jpg">
    

        <meta name="twitter:card" content="summary_large_image">

    

    
        <meta name="twitter:image" content="http://cyrus_huang.gitee.io/bloghttp://www.codeblocq.com/assets/projects/hexo-theme-clean-blog/img/home-bg.jpg">
    

    <!-- Title -->
    
    <title>V4L视频采集 - Cyrus的技术空间</title>

    <!-- Bootstrap Core CSS -->
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom CSS -->
    <link rel="stylesheet" href="/blog/css/style.css">

    <!-- Custom Fonts -->
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    <link href="//fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" rel="stylesheet" type="text/css">
    <link href="//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <!-- Gallery -->
    <link href="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.css" type="text/css" rel="stylesheet">

    <!-- Google Analytics -->
    


    <!-- favicon -->
    

</head>


<body>

    <!-- Menu -->
    <!-- Navigation -->
<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header page-scroll">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/blog/">Cyrus的技术空间</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav navbar-right">
                
                    <li>
                        <a href="/blog/">
                            
                                Home
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="/blog/archives">
                            
                                Archives
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="/blog/tags">
                            
                                Tags
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="/blog/categories">
                            
                                Categories
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="https://github.com/klugjo/hexo-theme-clean-blog">
                            
                                <i class="fa fa-github fa-stack-2x"></i>
                            
                        </a>
                    </li>
                
            </ul>
        </div>
        <!-- /.navbar-collapse -->
    </div>
    <!-- /.container -->
</nav>

    <!-- Main Content -->
    <!-- Page Header -->
<!-- Set your background image for this header in your post front-matter: cover -->

<header class="intro-header" style="background-image: url('http://www.codeblocq.com/assets/projects/hexo-theme-clean-blog/img/home-bg.jpg')">
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <div class="post-heading">
                    <h1>V4L视频采集</h1>
                    
                    <span class="meta">
                        <!-- Date and Author -->
                        
                            Posted by Cyrus on
                        
                        
                            2019-01-31
                        
                    </span>
                </div>
            </div>
        </div>
    </div>
</header>

<!-- Post Content -->
<article>
    <div class="container">
        <div class="row">

            <!-- Tags and categories -->
           
                <div class="col-lg-4 col-lg-offset-2 col-md-5 col-md-offset-1 post-tags">
                    
                        

<a href="/blog/categories/音视频/">音视频</a>

                    
                </div>
                <div class="col-lg-4 col-md-5 post-categories">
                    
                </div>
            

            <!-- Gallery -->
            

            <!-- Post Main Content -->
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <p>V4L是 Video for Linux的缩写,它是Linux 内核中关于视频设备的子系统，它为linux 下的视频驱动提供了统一的接口，使得应用程序可以使用统一的API 函数操作不同的视频设备，极大地简化了视频系统的开发和维护。<br>由于早期的 V4L 有很多缺陷，Bill Dirks 等人对其进行了重新设计，并取名为Video for Linux 2(V4L2使用)，最早出现于Linux2.5.x 版本。V4L2 相比于V4L 有更好的扩展性和灵活性，并且支持的硬件设备更多。<br>因此在应用程序V4L编程实际是指v4l2,我们这个系列的以V4L2为主,但由于历史的原因,V4L2一般兼容V4L.所以很多程序可以用V4L接口.</p>
<h3 id="工作流程"><a href="#工作流程" class="headerlink" title="工作流程"></a>工作流程</h3><p>打开设备－&gt; 检查和设置设备属性－&gt; 设置帧格式－&gt; 设置一种输入输出方法（缓冲区管理）－&gt; 循环获取数据－&gt; 关闭设备。</p>
<h4 id="1、打开设备"><a href="#1、打开设备" class="headerlink" title="1、打开设备"></a>1、打开设备</h4><p>一般V4L设备结点名是 /dev/videoN.如第一个V4L设备是/dev/video0.<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int fd = open(&quot;/dev/video0&quot;,O_RDWR |O_NONBLOCK);</span><br></pre></td></tr></table></figure></p>
<h4 id="2、检查和设置设备属性"><a href="#2、检查和设置设备属性" class="headerlink" title="2、检查和设置设备属性"></a>2、检查和设置设备属性</h4><p>主要通过ioctl来操作,格式<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl (int __fd, unsigned long int __request, .../*args*/) ;</span><br></pre></td></tr></table></figure></p>
<p>其中，__request是V4L2一些ioctl命令,常见如下.<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">VIDIOC_REQBUFS：分配内存</span><br><span class="line">VIDIOC_QUERYBUF：把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址</span><br><span class="line">VIDIOC_QUERYCAP：查询驱动功能</span><br><span class="line">VIDIOC_ENUM_FMT：获取当前驱动支持的视频格式</span><br><span class="line">VIDIOC_S_FMT：设置当前驱动的频捕获格式</span><br><span class="line">VIDIOC_G_FMT：读取当前驱动的频捕获格式</span><br><span class="line">VIDIOC_TRY_FMT：验证当前驱动的显示格式</span><br><span class="line">VIDIOC_CROPCAP：查询驱动的修剪能力</span><br><span class="line">VIDIOC_S_CROP：设置视频信号的边框</span><br><span class="line">VIDIOC_G_CROP：读取视频信号的边框</span><br><span class="line">VIDIOC_QBUF：把数据从缓存中读取出来</span><br><span class="line">VIDIOC_DQBUF：把数据放回缓存队列</span><br><span class="line">VIDIOC_STREAMON：开始视频显示函数</span><br><span class="line">VIDIOC_STREAMOFF：结束视频显示函数</span><br><span class="line">VIDIOC_QUERYSTD：检查当前视频设备支持的标准，例如PAL或NTSC。</span><br></pre></td></tr></table></figure></p>
<h4 id="2-1-查询设备属性：-VIDIOC-QUERYCAP"><a href="#2-1-查询设备属性：-VIDIOC-QUERYCAP" class="headerlink" title="2.1 查询设备属性： VIDIOC_QUERYCAP"></a>2.1 查询设备属性： VIDIOC_QUERYCAP</h4><p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_capability *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_capability  </span><br><span class="line">&#123;  </span><br><span class="line">u8 driver[16]; // 驱动名字  </span><br><span class="line">u8 card[32]; // 设备名字  </span><br><span class="line">u8 bus_info[32]; // 设备在系统中的位置  </span><br><span class="line">u32 version; // 驱动版本号  </span><br><span class="line">u32 capabilities; // 设备支持的操作  </span><br><span class="line">u32 reserved[4]; // 保留字段  </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<p>capabilities 常用值:</p>
<p>V4L2_CAP_VIDEO_CAPTURE // 是否支持图像获取</p>
<p>例：显示设备信息<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">struct v4l2_capability cap;    </span><br><span class="line">ioctl(fd,VIDIOC_QUERYCAP,&amp;cap);  </span><br><span class="line"> </span><br><span class="line">printf(“Driver Name:%s\nCard Name:%s\nBus info:%s\nDriver Version:%u.%u.%u\n”,cap.driver,cap.card,cap.bus_info,(cap.version&gt;&gt;16)&amp;0XFF, (cap.version&gt;&gt;8)&amp;0XFF,cap.version&amp;0XFF);</span><br></pre></td></tr></table></figure></p>
<h4 id="3、设置视频的制式和帧格式"><a href="#3、设置视频的制式和帧格式" class="headerlink" title="3、设置视频的制式和帧格式"></a>3、设置视频的制式和帧格式</h4><p>制式包括PAL，NTSC，帧的格式个包括宽度和高度等。</p>
<p>相关函数<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_fmtdesc *argp);  </span><br><span class="line">  </span><br><span class="line">int ioctl(int fd, int request, struct v4l2_format *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：</p>
<p><font color="ff0000">v4l2_cropcap</font> 结构体用来设置摄像头的捕捉能力，在捕捉上视频时应先先设置</p>
<p>v4l2_cropcap 的 type 域，再通过 VIDIO_CROPCAP 操作命令获取设备捕捉能力的参数，保存于 v4l2_cropcap 结构体中，包括 bounds（最大捕捉方框的左上角坐标和宽高），defrect（默认捕捉方框的左上角坐标和宽高）等。</p>
<p>v4l2_format 结构体用来设置摄像头的视频制式、帧格式等，在设置这个参数时应先填 好 v4l2_format 的各个域，如 type（传输流类型），fmt.pix.width(宽)，fmt.pix.heigth(高)，fmt.pix.field(采样区域，如隔行采样)，fmt.pix.pixelformat(采样类型，如 YUV4:2:2)，然后通过 VIDIO_S_FMT 操作命令设置视频捕捉格式。</p>
<h4 id="3-1-查询并显示所有支持的格式：VIDIOC-ENUM-FMT"><a href="#3-1-查询并显示所有支持的格式：VIDIOC-ENUM-FMT" class="headerlink" title="3.1 查询并显示所有支持的格式：VIDIOC_ENUM_FMT"></a>3.1 查询并显示所有支持的格式：VIDIOC_ENUM_FMT</h4><p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_fmtdesc *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_fmtdesc   </span><br><span class="line">&#123;   </span><br><span class="line">u32 index; // 要查询的格式序号，应用程序设置  </span><br><span class="line">enum v4l2_buf_type type; // 帧类型，应用程序设置  </span><br><span class="line">u32 flags; // 是否为压缩格式  </span><br><span class="line">u8 description[32]; // 格式名称  </span><br><span class="line">u32 pixelformat; // 格式  </span><br><span class="line">u32 reserved[4]; // 保留   </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<p>例：显示所有支持的格式<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_fmtdesc fmtdesc; </span><br><span class="line">fmtdesc.index=0; </span><br><span class="line">fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; </span><br><span class="line">printf(&quot;Support format:\n&quot;);  </span><br><span class="line">while(ioctl(fd, VIDIOC_ENUM_FMT, &amp;fmtdesc) != -1)  </span><br><span class="line">&#123;  </span><br><span class="line">	printf(&quot;\t%d.%s\n&quot;,fmtdesc.index+1,fmtdesc.description);  </span><br><span class="line">	fmtdesc.index++;   </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h4 id="3-2-查看或设置当前格式：-VIDIOC-G-FMT-VIDIOC-S-FMT"><a href="#3-2-查看或设置当前格式：-VIDIOC-G-FMT-VIDIOC-S-FMT" class="headerlink" title="3.2 查看或设置当前格式： VIDIOC_G_FMT, VIDIOC_S_FMT"></a>3.2 查看或设置当前格式： VIDIOC_G_FMT, VIDIOC_S_FMT</h4><p>检查是否支持某种格式：VIDIOC_TRY_FMT</p>
<p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_format *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_format  </span><br><span class="line">&#123;  </span><br><span class="line">	enum v4l2_buf_type type; // 帧类型，应用程序设置  </span><br><span class="line">	union fmt  &#123;  </span><br><span class="line">        struct v4l2_pix_format pix; // 视频设备使用  </span><br><span class="line">        struct v4l2_window win;  </span><br><span class="line">        struct v4l2_vbi_format vbi;  </span><br><span class="line">        struct v4l2_sliced_vbi_format sliced;  </span><br><span class="line">        u8 raw_data[200];  </span><br><span class="line">    &#125;;  </span><br><span class="line">&#125;;  </span><br><span class="line">  </span><br><span class="line">struct v4l2_pix_format  </span><br><span class="line">&#123;  </span><br><span class="line">    u32 width; // 帧宽，单位像素  </span><br><span class="line">    u32 height; // 帧高，单位像素  </span><br><span class="line">    u32 pixelformat; // 帧格式  </span><br><span class="line">    enum v4l2_field field;  </span><br><span class="line">    u32 bytesperline;  </span><br><span class="line">    u32 sizeimage;  </span><br><span class="line">    enum v4l2_colorspace colorspace;  </span><br><span class="line">    u32 priv;  </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<p>例:显示当前帧的相关信息<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_format fmt;  </span><br><span class="line">  </span><br><span class="line">fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">  </span><br><span class="line">ioctl(fd, VIDIOC_G_FMT, &amp;fmt);  </span><br><span class="line">  </span><br><span class="line">printf(“Current data format information:\n\twidth:%d\n\theight:%d\n”, fmt.fmt.pix.width,fmt.fmt.pix.height);  </span><br><span class="line">  </span><br><span class="line">struct v4l2_fmtdesc fmtdesc;  </span><br><span class="line">  </span><br><span class="line">fmtdesc.index = 0;  </span><br><span class="line">  </span><br><span class="line">fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">  </span><br><span class="line">while(ioctl(fd,VIDIOC_ENUM_FMT,&amp;fmtdesc) != -1)  </span><br><span class="line">&#123;  </span><br><span class="line">    if(fmtdesc.pixelformat &amp; fmt.fmt.pix.pixelformat)  </span><br><span class="line">    &#123;  </span><br><span class="line">        printf(“\tformat:%s\n”,fmtdesc.description);  </span><br><span class="line">        break;  </span><br><span class="line">    &#125;  </span><br><span class="line">    fmtdesc.index++;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>例：检查是否支持某种帧格式<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_format fmt;   </span><br><span class="line">  </span><br><span class="line">fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   </span><br><span class="line">  </span><br><span class="line">fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;   </span><br><span class="line">  </span><br><span class="line">if(ioctl(fd,VIDIOC_TRY_FMT,&amp;fmt) == -1)   </span><br><span class="line">&#123;  </span><br><span class="line">    if(errno==EINVAL)  </span><br><span class="line">    &#123;  </span><br><span class="line">        printf(“not support format RGB32!\n”);  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h4 id="3-3-图像的缩放-VIDIOC-CROPCAP"><a href="#3-3-图像的缩放-VIDIOC-CROPCAP" class="headerlink" title="3.3 图像的缩放 VIDIOC_CROPCAP"></a>3.3 图像的缩放 VIDIOC_CROPCAP</h4><p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_cropcap *argp);  </span><br><span class="line">int ioctl(int fd, int request, struct v4l2_crop *argp);  </span><br><span class="line">int ioctl(int fd, int request, const struct v4l2_crop *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：</p>
<p>v4l2_cropcap 结构体用来设置摄像头的捕捉能力，在捕捉上视频时应先先设置v4l2_cropcap 的 type 域，再通过 VIDIO_CROPCAP 操作命令获取设备捕捉能力的参数，保存于 v4l2_cropcap 结构体中，包括 bounds（最大捕捉方框的左上角坐标和宽高），defrect（默认捕捉方框的左上角坐标和宽高）等。</p>
<p>Cropping 和 scaling 主要指的是图像的取景范围及图片的比例缩放的支持。Crop 就 是把得到的数据作一定的裁剪和伸缩，裁剪可以只取样我们可以得到的图像大小的一部分， 剪裁的主要参数是位置、长度、宽度。而 scale 的设置是通过 VIDIOC_G_FMT 和 VIDIOC_S_FMT 来获得和设置当前的 image 的长度，宽度来实现的。</p>
<p>我们可以假设 bounds 是 sensor 最大能捕捉到的图像范围，而 defrect 是设备默认 的最大取样范围，这个可以通过 VIDIOC_CROPCAP 的 ioctl 来获得设备的 crap 相关的属 性 v4l2_cropcap，其中的 bounds 就是这个 bounds，其实就是上限。每个设备都有个默 认的取样范围，就是 defrect，就是 default rect 的意思，它比 bounds 要小一些。这 个范围也是通过 VIDIOC_CROPCAP 的 ioctl 来获得的 v4l2_cropcap 结构中的 defrect 来表示的，我们可以通过 VIDIOC_G_CROP 和 VIDIOC_S_CROP 来获取和设置设备当前的 crop 设置。</p>
<h4 id="3-4-设置设备捕捉能力的参数"><a href="#3-4-设置设备捕捉能力的参数" class="headerlink" title="3.4 设置设备捕捉能力的参数"></a>3.4 设置设备捕捉能力的参数</h4><p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_cropcap *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_cropcap  </span><br><span class="line">&#123;  </span><br><span class="line">    enum v4l2_buf_type type; // 数据流的类型，应用程序设置  </span><br><span class="line">    struct v4l2_rect bounds; // 这是 camera 的镜头能捕捉到的窗口大小的局限  </span><br><span class="line">    struct v4l2_rect defrect; // 定义默认窗口大小，包括起点位置及长,宽的大小，大小以像素为单位  </span><br><span class="line">    struct v4l2_fract pixelaspect; // 定义了图片的宽高比  </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<h4 id="3-5-设置窗口取景参数-VIDIOC-G-CROP-和-VIDIOC-S-CROP"><a href="#3-5-设置窗口取景参数-VIDIOC-G-CROP-和-VIDIOC-S-CROP" class="headerlink" title="3.5 设置窗口取景参数 VIDIOC_G_CROP 和 VIDIOC_S_CROP"></a>3.5 设置窗口取景参数 VIDIOC_G_CROP 和 VIDIOC_S_CROP</h4><p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_crop *argp);  </span><br><span class="line">int ioctl(int fd, int request, const struct v4l2_crop *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_crop  </span><br><span class="line">&#123;  </span><br><span class="line">    enum v4l2_buf_type type;// 应用程序设置  </span><br><span class="line">    struct v4l2_rect c;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h4 id="3-6-video-Inputs-and-Outputs"><a href="#3-6-video-Inputs-and-Outputs" class="headerlink" title="3.6 video Inputs and Outputs"></a>3.6 video Inputs and Outputs</h4><p>VIDIOC_G_INPUT 和 VIDIOC_S_INPUT 用来查询和选则当前的 input，一个 video 设备 节点可能对应多个视频源，比如 saf7113 可以最多支持四路 cvbs 输入，如果上层想在四 个cvbs视频输入间切换，那么就要调用 ioctl(fd, VIDIOC_S_INPUT, &amp;input) 来切换。VIDIOC_G_INPUT and VIDIOC_G_OUTPUT 返回当前的 video input和output的index.</p>
<p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_input *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_input   </span><br><span class="line">&#123;  </span><br><span class="line">    __u32 index;    /* Which input */  </span><br><span class="line">    __u8 name[32];  /* Label */  </span><br><span class="line">    __u32 type;     /* Type of input */  </span><br><span class="line">    __u32 audioset; /* Associated audios (bitfield) */  </span><br><span class="line">    __u32 tuner;    /* Associated tuner */  </span><br><span class="line">    v4l2_std_id std;  </span><br><span class="line">    __u32 status;  </span><br><span class="line">    __u32 reserved[4];  </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<p>我们可以通过VIDIOC_ENUMINPUT and VIDIOC_ENUMOUTPUT 分别列举一个input或者 output的信息，我们使用一个v4l2_input结构体来存放查询结果，这个结构体中有一个 index域用来指定你索要查询的是第几个input/ouput,如果你所查询的这个input是当前正 在使用的，那么在v4l2_input还会包含一些当前的状态信息，如果所 查询的input/output 不存在，那么回返回EINVAL错误，所以，我们通过循环查找，直到返回错误来遍历所有的 input/output. VIDIOC_G_INPUT and VIDIOC_G_OUTPUT 返回当前的video input和output 的index.</p>
<h3 id="4、申请和管理缓冲区"><a href="#4、申请和管理缓冲区" class="headerlink" title="4、申请和管理缓冲区"></a>4、申请和管理缓冲区</h3><p>应用程序和设备有三种交换数据的方法，直接 read/write、内存映射(memory mapping)和用户指针。这里只讨论内存映射(memory mapping)。</p>
<h4 id="4-1-向设备申请缓冲区-VIDIOC-REQBUFS"><a href="#4-1-向设备申请缓冲区-VIDIOC-REQBUFS" class="headerlink" title="4.1 向设备申请缓冲区 VIDIOC_REQBUFS"></a>4.1 向设备申请缓冲区 VIDIOC_REQBUFS</h4><p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_requestbuffers *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_requestbuffers  </span><br><span class="line">&#123;  </span><br><span class="line">    u32 count; // 缓冲区内缓冲帧的数目  </span><br><span class="line">    enum v4l2_buf_type type; // 缓冲帧数据格式  </span><br><span class="line">    enum v4l2_memory memory; // 区别是内存映射还是用户指针方式  </span><br><span class="line">    u32 reserved[2];  </span><br><span class="line">&#125;; </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">注：</span><br><span class="line">enum v4l2_memoy</span><br><span class="line">&#123;</span><br><span class="line">    V4L2_MEMORY_MMAP, V4L2_MEMORY_USERPTR</span><br><span class="line"></span><br><span class="line">&#125;;</span><br><span class="line">//count,type,memory 都要应用程序设置</span><br></pre></td></tr></table></figure></p>
<p>例：申请一个拥有四个缓冲帧的缓冲区<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_requestbuffers req;   </span><br><span class="line">req.count = 4;    </span><br><span class="line">req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   </span><br><span class="line">req.memory = V4L2_MEMORY_MMAP;   </span><br><span class="line">ioctl(fd,VIDIOC_REQBUFS,&amp;req);</span><br></pre></td></tr></table></figure></p>
<h4 id="4-2-获取缓冲帧的地址，长度：VIDIOC-QUERYBUF"><a href="#4-2-获取缓冲帧的地址，长度：VIDIOC-QUERYBUF" class="headerlink" title="4.2 获取缓冲帧的地址，长度：VIDIOC_QUERYBUF"></a>4.2 获取缓冲帧的地址，长度：VIDIOC_QUERYBUF</h4><p>相关函数:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, struct v4l2_buffer *argp);</span><br></pre></td></tr></table></figure></p>
<p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_buffer  </span><br><span class="line">&#123;  </span><br><span class="line">    u32 index; //buffer 序号  </span><br><span class="line">    enum v4l2_buf_type type; //buffer 类型  </span><br><span class="line">    u32 byteused; //buffer 中已使用的字节数  </span><br><span class="line">    u32 flags; // 区分是MMAP 还是USERPTR  </span><br><span class="line">    enum v4l2_field field;  </span><br><span class="line">    struct timeval timestamp; // 获取第一个字节时的系统时间  </span><br><span class="line">    struct v4l2_timecode timecode;  </span><br><span class="line">    u32 sequence; // 队列中的序号  </span><br><span class="line">    enum v4l2_memory memory; //IO 方式，被应用程序设置  </span><br><span class="line">    union m  </span><br><span class="line">    &#123;  </span><br><span class="line">        u32 offset; // 缓冲帧地址，只对MMAP 有效  </span><br><span class="line">        unsigned long userptr;  </span><br><span class="line">    &#125;;  </span><br><span class="line">    u32 length; // 缓冲帧长度  </span><br><span class="line">    u32 input;  </span><br><span class="line">    u32 reserved;  </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<h4 id="4-3-内存映射MMAP-及定义一个结构体来映射每个缓冲帧"><a href="#4-3-内存映射MMAP-及定义一个结构体来映射每个缓冲帧" class="headerlink" title="4.3 内存映射MMAP 及定义一个结构体来映射每个缓冲帧"></a>4.3 内存映射MMAP 及定义一个结构体来映射每个缓冲帧</h4><p>相关结构体：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">struct buffer  </span><br><span class="line">&#123;  </span><br><span class="line">    void* start;  </span><br><span class="line">    unsigned int length;  </span><br><span class="line">&#125;*buffers;</span><br></pre></td></tr></table></figure></p>
<p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) </span><br><span class="line"></span><br><span class="line">//addr 映射起始地址，一般为NULL ，让内核自动选择</span><br><span class="line">//length 被映射内存块的长度</span><br><span class="line">//prot 标志映射后能否被读写，其值为PROT_EXEC,PROT_READ,PROT_WRITE, PROT_NONE</span><br><span class="line">//flags 确定此内存映射能否被其他进程共享，MAP_SHARED,MAP_PRIVATE</span><br><span class="line">//fd,offset, 确定被映射的内存地址 返回成功映射后的地址，不成功返回MAP_FAILED ((void*)-1)</span><br></pre></td></tr></table></figure></p>
<p>相关函数：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">int munmap(void *addr, size_t length);// 断开映射  </span><br><span class="line"></span><br><span class="line">//addr 为映射后的地址，length 为映射后的内存长度</span><br></pre></td></tr></table></figure></p>
<h3 id="5、启动-或-停止数据流-VIDIOC-STREAMON，-VIDIOC-STREAMOFF"><a href="#5、启动-或-停止数据流-VIDIOC-STREAMON，-VIDIOC-STREAMOFF" class="headerlink" title="5、启动 或 停止数据流 VIDIOC_STREAMON， VIDIOC_STREAMOFF"></a>5、启动 或 停止数据流 VIDIOC_STREAMON， VIDIOC_STREAMOFF</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">int ioctl(int fd, int request, const int *argp);</span><br><span class="line"></span><br><span class="line">//argp 为流类型指针，如V4L2_BUF_TYPE_VIDEO_CAPTURE.</span><br></pre></td></tr></table></figure>
<h4 id="5-1-在开始之前，还应当把缓冲帧放入缓冲队列："><a href="#5-1-在开始之前，还应当把缓冲帧放入缓冲队列：" class="headerlink" title="5.1 在开始之前，还应当把缓冲帧放入缓冲队列："></a>5.1 在开始之前，还应当把缓冲帧放入缓冲队列：</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">VIDIOC_QBUF		//把帧放入队列</span><br><span class="line">VIDIOC_DQBUF	//从队列中取出帧</span><br><span class="line"></span><br><span class="line">int ioctl(int fd, int request, struct v4l2_buffer *argp);</span><br></pre></td></tr></table></figure>
<p>例：把四个缓冲帧放入队列，并启动数据流<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">unsigned int i;   </span><br><span class="line">enum v4l2_buf_type type;  </span><br><span class="line">for (i = 0; i &lt; 4; ++i) // 将缓冲帧放入队列  </span><br><span class="line">&#123;  </span><br><span class="line">    struct v4l2_buffer buf;  </span><br><span class="line">    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">    buf.memory = V4L2_MEMORY_MMAP;  </span><br><span class="line">    buf.index = i;  </span><br><span class="line">    ioctl (fd, VIDIOC_QBUF, &amp;buf);  </span><br><span class="line">&#125;  </span><br><span class="line">type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">ioctl (fd, VIDIOC_STREAMON, &amp;type);</span><br></pre></td></tr></table></figure></p>
<p>例：获取一帧并处理<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">struct v4l2_buffer buf; </span><br><span class="line">CLEAR (buf);  </span><br><span class="line">buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">buf.memory = V4L2_MEMORY_MMAP;  </span><br><span class="line">ioctl (fd, VIDIOC_DQBUF, &amp;buf); // 从缓冲区取出一个缓冲帧  </span><br><span class="line">process_image (buffers[buf.index].start); //  </span><br><span class="line">ioctl (fd，VIDIOC_QBUF，&amp;buf); //</span><br></pre></td></tr></table></figure></p>
<p>附官方 v4l2 video capture example<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br><span class="line">590</span><br><span class="line">591</span><br><span class="line">592</span><br><span class="line">593</span><br><span class="line">594</span><br><span class="line">595</span><br><span class="line">596</span><br><span class="line">597</span><br><span class="line">598</span><br><span class="line">599</span><br><span class="line">600</span><br><span class="line">601</span><br><span class="line">602</span><br><span class="line">603</span><br><span class="line">604</span><br><span class="line">605</span><br><span class="line">606</span><br><span class="line">607</span><br><span class="line">608</span><br><span class="line">609</span><br><span class="line">610</span><br><span class="line">611</span><br><span class="line">612</span><br><span class="line">613</span><br><span class="line">614</span><br><span class="line">615</span><br><span class="line">616</span><br><span class="line">617</span><br><span class="line">618</span><br><span class="line">619</span><br><span class="line">620</span><br><span class="line">621</span><br><span class="line">622</span><br><span class="line">623</span><br><span class="line">624</span><br><span class="line">625</span><br><span class="line">626</span><br><span class="line">627</span><br><span class="line">628</span><br><span class="line">629</span><br><span class="line">630</span><br><span class="line">631</span><br><span class="line">632</span><br><span class="line">633</span><br><span class="line">634</span><br><span class="line">635</span><br><span class="line">636</span><br><span class="line">637</span><br><span class="line">638</span><br><span class="line">639</span><br><span class="line">640</span><br><span class="line">641</span><br><span class="line">642</span><br><span class="line">643</span><br><span class="line">644</span><br><span class="line">645</span><br><span class="line">646</span><br><span class="line">647</span><br><span class="line">648</span><br><span class="line">649</span><br><span class="line">650</span><br><span class="line">651</span><br><span class="line">652</span><br><span class="line">653</span><br><span class="line">654</span><br><span class="line">655</span><br><span class="line">656</span><br><span class="line">657</span><br><span class="line">658</span><br><span class="line">659</span><br><span class="line">660</span><br><span class="line">661</span><br><span class="line">662</span><br><span class="line">663</span><br><span class="line">664</span><br><span class="line">665</span><br><span class="line">666</span><br><span class="line">667</span><br><span class="line">668</span><br><span class="line">669</span><br><span class="line">670</span><br><span class="line">671</span><br><span class="line">672</span><br><span class="line">673</span><br><span class="line">674</span><br><span class="line">675</span><br><span class="line">676</span><br><span class="line">677</span><br><span class="line">678</span><br><span class="line">679</span><br><span class="line">680</span><br><span class="line">681</span><br><span class="line">682</span><br><span class="line">683</span><br><span class="line">684</span><br><span class="line">685</span><br><span class="line">686</span><br><span class="line">687</span><br><span class="line">688</span><br><span class="line">689</span><br><span class="line">690</span><br><span class="line">691</span><br><span class="line">692</span><br><span class="line">693</span><br></pre></td><td class="code"><pre><span class="line">/* </span><br><span class="line"> *  V4L2 video capture example </span><br><span class="line"> * </span><br><span class="line"> *  This program can be used and distributed without restrictions. </span><br><span class="line"> * </span><br><span class="line"> *      This program is provided with the V4L2 API </span><br><span class="line"> * see http://linuxtv.org/docs.php for more information </span><br><span class="line"> */  </span><br><span class="line">  </span><br><span class="line">#include &lt;stdio.h&gt;  </span><br><span class="line">#include &lt;stdlib.h&gt;  </span><br><span class="line">#include &lt;string.h&gt;  </span><br><span class="line">#include &lt;assert.h&gt;  </span><br><span class="line">  </span><br><span class="line">#include &lt;getopt.h&gt;             /* getopt_long() */  </span><br><span class="line">  </span><br><span class="line">#include &lt;fcntl.h&gt;              /* low-level i/o */  </span><br><span class="line">#include &lt;unistd.h&gt;  </span><br><span class="line">#include &lt;errno.h&gt;  </span><br><span class="line">#include &lt;sys/stat.h&gt;  </span><br><span class="line">#include &lt;sys/types.h&gt;  </span><br><span class="line">#include &lt;sys/time.h&gt;  </span><br><span class="line">#include &lt;sys/mman.h&gt;  </span><br><span class="line">#include &lt;sys/ioctl.h&gt;  </span><br><span class="line">  </span><br><span class="line">#include &lt;linux/videodev2.h&gt;  </span><br><span class="line">  </span><br><span class="line">#define CLEAR(x) memset(&amp;(x), 0, sizeof(x))  </span><br><span class="line">  </span><br><span class="line">enum io_method &#123;  </span><br><span class="line">        IO_METHOD_READ,  </span><br><span class="line">        IO_METHOD_MMAP,  </span><br><span class="line">        IO_METHOD_USERPTR,  </span><br><span class="line">&#125;;  </span><br><span class="line">  </span><br><span class="line">struct buffer &#123;  </span><br><span class="line">        void   *start;  </span><br><span class="line">        size_t  length;  </span><br><span class="line">&#125;;  </span><br><span class="line">  </span><br><span class="line">static char            *dev_name;  </span><br><span class="line">static enum io_method   io = IO_METHOD_MMAP;  </span><br><span class="line">static int              fd = -1;  </span><br><span class="line">struct buffer          *buffers;  </span><br><span class="line">static unsigned int     n_buffers;  </span><br><span class="line">static int              out_buf;  </span><br><span class="line">static int              force_format;  </span><br><span class="line">static int              frame_count = 70;  </span><br><span class="line">  </span><br><span class="line">/* </span><br><span class="line"> * </span><br><span class="line"> * </span><br><span class="line"> * </span><br><span class="line"> * </span><br><span class="line"> */  </span><br><span class="line">static void errno_exit(const char *s)  </span><br><span class="line">&#123;  </span><br><span class="line">        fprintf(stderr, &quot;%s error %d, %s\n&quot;, s, errno, strerror(errno));  </span><br><span class="line">        exit(EXIT_FAILURE);  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">static int xioctl(int fh, int request, void *arg)  </span><br><span class="line">&#123;  </span><br><span class="line">        int r;  </span><br><span class="line">  </span><br><span class="line">        do &#123;  </span><br><span class="line">                r = ioctl(fh, request, arg);  </span><br><span class="line">        &#125; while (-1 == r &amp;&amp; EINTR == errno);  </span><br><span class="line">  </span><br><span class="line">        return r;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">static void process_image(const void *p, int size)  </span><br><span class="line">&#123;  </span><br><span class="line">        if (out_buf)  </span><br><span class="line">                fwrite(p, size, 1, stdout);  </span><br><span class="line">  </span><br><span class="line">        fflush(stderr);  </span><br><span class="line">        fprintf(stderr, &quot;.&quot;);  </span><br><span class="line">        fflush(stdout);  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">static int read_frame(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        struct v4l2_buffer buf;  </span><br><span class="line">        unsigned int i;  </span><br><span class="line">  </span><br><span class="line">        switch (io) &#123;  </span><br><span class="line">        case IO_METHOD_READ:  </span><br><span class="line">                if (-1 == read(fd, buffers[0].start, buffers[0].length)) &#123;  </span><br><span class="line">                        switch (errno) &#123;  </span><br><span class="line">                        case EAGAIN:  </span><br><span class="line">                                return 0;  </span><br><span class="line">  </span><br><span class="line">                        case EIO:  </span><br><span class="line">                                /* Could ignore EIO, see spec. */  </span><br><span class="line">  </span><br><span class="line">                                /* fall through */  </span><br><span class="line">  </span><br><span class="line">                        default:  </span><br><span class="line">                                errno_exit(&quot;read&quot;);  </span><br><span class="line">                        &#125;  </span><br><span class="line">                &#125;  </span><br><span class="line">  </span><br><span class="line">                process_image(buffers[0].start, buffers[0].length);  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_MMAP:  </span><br><span class="line">                CLEAR(buf);  </span><br><span class="line">  </span><br><span class="line">                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                buf.memory = V4L2_MEMORY_MMAP;  </span><br><span class="line">  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_DQBUF, &amp;buf)) &#123;  </span><br><span class="line">                        switch (errno) &#123;  </span><br><span class="line">                        case EAGAIN:  </span><br><span class="line">                                return 0;  </span><br><span class="line">  </span><br><span class="line">                        case EIO:  </span><br><span class="line">                                /* Could ignore EIO, see spec. */  </span><br><span class="line">  </span><br><span class="line">                                /* fall through */  </span><br><span class="line">  </span><br><span class="line">                        default:  </span><br><span class="line">                                errno_exit(&quot;VIDIOC_DQBUF&quot;);  </span><br><span class="line">                        &#125;  </span><br><span class="line">                &#125;  </span><br><span class="line">  </span><br><span class="line">                assert(buf.index &lt; n_buffers);  </span><br><span class="line">  </span><br><span class="line">                process_image(buffers[buf.index].start, buf.bytesused);  </span><br><span class="line">  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_QBUF&quot;);  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_USERPTR:  </span><br><span class="line">                CLEAR(buf);  </span><br><span class="line">  </span><br><span class="line">                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                buf.memory = V4L2_MEMORY_USERPTR;  </span><br><span class="line">  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_DQBUF, &amp;buf)) &#123;  </span><br><span class="line">                        switch (errno) &#123;  </span><br><span class="line">                        case EAGAIN:  </span><br><span class="line">                                return 0;  </span><br><span class="line">  </span><br><span class="line">                        case EIO:  </span><br><span class="line">                                /* Could ignore EIO, see spec. */  </span><br><span class="line">  </span><br><span class="line">                                /* fall through */  </span><br><span class="line">  </span><br><span class="line">                        default:  </span><br><span class="line">                                errno_exit(&quot;VIDIOC_DQBUF&quot;);  </span><br><span class="line">                        &#125;  </span><br><span class="line">                &#125;  </span><br><span class="line">  </span><br><span class="line">                for (i = 0; i &lt; n_buffers; ++i)  </span><br><span class="line">                        if (buf.m.userptr == (unsigned long)buffers[i].start  </span><br><span class="line">                            &amp;&amp; buf.length == buffers[i].length)  </span><br><span class="line">                                break;  </span><br><span class="line">  </span><br><span class="line">                assert(i &lt; n_buffers);  </span><br><span class="line">  </span><br><span class="line">                process_image((void *)buf.m.userptr, buf.bytesused);  </span><br><span class="line">  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_QBUF&quot;);  </span><br><span class="line">                break;  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        return 1;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">/* two operations </span><br><span class="line"> * step1 : delay </span><br><span class="line"> * step2 : read frame </span><br><span class="line"> */  </span><br><span class="line">static void mainloop(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        unsigned int count;  </span><br><span class="line">  </span><br><span class="line">        count = frame_count;  </span><br><span class="line">  </span><br><span class="line">        while (count-- &gt; 0) &#123;  </span><br><span class="line">                for (;;) &#123;  </span><br><span class="line">                        fd_set fds;  </span><br><span class="line">                        struct timeval tv;  </span><br><span class="line">                        int r;  </span><br><span class="line">  </span><br><span class="line">                        FD_ZERO(&amp;fds);  </span><br><span class="line">                        FD_SET(fd, &amp;fds);  </span><br><span class="line">  </span><br><span class="line">                        /* Timeout. */  </span><br><span class="line">                        tv.tv_sec = 2;  </span><br><span class="line">                        tv.tv_usec = 0;  </span><br><span class="line">  </span><br><span class="line">                        r = select(fd + 1, &amp;fds, NULL, NULL, &amp;tv);  </span><br><span class="line">  </span><br><span class="line">                        if (-1 == r) &#123;  </span><br><span class="line">                                if (EINTR == errno)  </span><br><span class="line">                                        continue;  </span><br><span class="line">                                errno_exit(&quot;select&quot;);  </span><br><span class="line">                        &#125;  </span><br><span class="line">  </span><br><span class="line">                        if (0 == r) &#123;  </span><br><span class="line">                                fprintf(stderr, &quot;select timeout\n&quot;);  </span><br><span class="line">                                exit(EXIT_FAILURE);  </span><br><span class="line">                        &#125;  </span><br><span class="line">  </span><br><span class="line">                        if (read_frame())  </span><br><span class="line">                                break;  </span><br><span class="line">                        /* EAGAIN - continue select loop. */  </span><br><span class="line">                &#125;  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">/* </span><br><span class="line"> * one operation </span><br><span class="line"> * step1 : VIDIOC_STREAMOFF </span><br><span class="line"> */  </span><br><span class="line">static void stop_capturing(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        enum v4l2_buf_type type;  </span><br><span class="line">  </span><br><span class="line">        switch (io) &#123;  </span><br><span class="line">        case IO_METHOD_READ:  </span><br><span class="line">                /* Nothing to do. */  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_MMAP:  </span><br><span class="line">        case IO_METHOD_USERPTR:  </span><br><span class="line">                type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &amp;type))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_STREAMOFF&quot;);  </span><br><span class="line">                break;  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">/* tow operations </span><br><span class="line"> * step1 : VIDIOC_QBUF(insert buffer to queue) </span><br><span class="line"> * step2 : VIDIOC_STREAMOFF </span><br><span class="line"> */  </span><br><span class="line">static void start_capturing(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        unsigned int i;  </span><br><span class="line">        enum v4l2_buf_type type;  </span><br><span class="line">  </span><br><span class="line">        switch (io) &#123;  </span><br><span class="line">        case IO_METHOD_READ:  </span><br><span class="line">                /* Nothing to do. */  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_MMAP:  </span><br><span class="line">                for (i = 0; i &lt; n_buffers; ++i) &#123;  </span><br><span class="line">                        struct v4l2_buffer buf;  </span><br><span class="line">  </span><br><span class="line">                        CLEAR(buf);  </span><br><span class="line">                        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                        buf.memory = V4L2_MEMORY_MMAP;  </span><br><span class="line">                        buf.index = i;  </span><br><span class="line">  </span><br><span class="line">                        if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))  </span><br><span class="line">                                errno_exit(&quot;VIDIOC_QBUF&quot;);  </span><br><span class="line">                &#125;  </span><br><span class="line">                type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_STREAMON, &amp;type))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_STREAMON&quot;);  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_USERPTR:  </span><br><span class="line">                for (i = 0; i &lt; n_buffers; ++i) &#123;  </span><br><span class="line">                        struct v4l2_buffer buf;  </span><br><span class="line">  </span><br><span class="line">                        CLEAR(buf);  </span><br><span class="line">                        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                        buf.memory = V4L2_MEMORY_USERPTR;  </span><br><span class="line">                        buf.index = i;  </span><br><span class="line">                        buf.m.userptr = (unsigned long)buffers[i].start;  </span><br><span class="line">                        buf.length = buffers[i].length;  </span><br><span class="line">  </span><br><span class="line">                        if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))  </span><br><span class="line">                                errno_exit(&quot;VIDIOC_QBUF&quot;);  </span><br><span class="line">                &#125;  </span><br><span class="line">                type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_STREAMON, &amp;type))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_STREAMON&quot;);  </span><br><span class="line">                break;  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">/* two operations </span><br><span class="line"> * step1 : munmap buffers </span><br><span class="line"> * steo2 : free buffers </span><br><span class="line"> */  </span><br><span class="line">static void uninit_device(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        unsigned int i;  </span><br><span class="line">  </span><br><span class="line">        switch (io) &#123;  </span><br><span class="line">        case IO_METHOD_READ:  </span><br><span class="line">                free(buffers[0].start);  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_MMAP:  </span><br><span class="line">                for (i = 0; i &lt; n_buffers; ++i)  </span><br><span class="line">                        if (-1 == munmap(buffers[i].start, buffers[i].length))  </span><br><span class="line">                                errno_exit(&quot;munmap&quot;);  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_USERPTR:  </span><br><span class="line">                for (i = 0; i &lt; n_buffers; ++i)  </span><br><span class="line">                        free(buffers[i].start);  </span><br><span class="line">                break;  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        free(buffers);  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">static void init_read(unsigned int buffer_size)  </span><br><span class="line">&#123;  </span><br><span class="line">        buffers = calloc(1, sizeof(*buffers));  </span><br><span class="line">  </span><br><span class="line">        if (!buffers) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;Out of memory\n&quot;);  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        buffers[0].length = buffer_size;  </span><br><span class="line">        buffers[0].start = malloc(buffer_size);  </span><br><span class="line">  </span><br><span class="line">        if (!buffers[0].start) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;Out of memory\n&quot;);  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">static void init_mmap(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        struct v4l2_requestbuffers req;  </span><br><span class="line">  </span><br><span class="line">        CLEAR(req);  </span><br><span class="line">  </span><br><span class="line">        req.count = 4;  </span><br><span class="line">        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">        req.memory = V4L2_MEMORY_MMAP;  </span><br><span class="line">  </span><br><span class="line">        if (-1 == xioctl(fd, VIDIOC_REQBUFS, &amp;req)) &#123;  </span><br><span class="line">                if (EINVAL == errno) &#123;  </span><br><span class="line">                        fprintf(stderr, &quot;%s does not support &quot;  </span><br><span class="line">                                 &quot;memory mapping\n&quot;, dev_name);  </span><br><span class="line">                        exit(EXIT_FAILURE);  </span><br><span class="line">                &#125; else &#123;  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_REQBUFS&quot;);  </span><br><span class="line">                &#125;  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        if (req.count &lt; 2) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;Insufficient buffer memory on %s\n&quot;,  </span><br><span class="line">                         dev_name);  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        buffers = calloc(req.count, sizeof(*buffers));  </span><br><span class="line">  </span><br><span class="line">        if (!buffers) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;Out of memory\n&quot;);  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        for (n_buffers = 0; n_buffers &lt; req.count; ++n_buffers) &#123;  </span><br><span class="line">                struct v4l2_buffer buf;  </span><br><span class="line">  </span><br><span class="line">                CLEAR(buf);  </span><br><span class="line">  </span><br><span class="line">                buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                buf.memory      = V4L2_MEMORY_MMAP;  </span><br><span class="line">                buf.index       = n_buffers;  </span><br><span class="line">  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &amp;buf))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_QUERYBUF&quot;);  </span><br><span class="line">  </span><br><span class="line">                buffers[n_buffers].length = buf.length;  </span><br><span class="line">                buffers[n_buffers].start =  </span><br><span class="line">                        mmap(NULL /* start anywhere */,  </span><br><span class="line">                              buf.length,  </span><br><span class="line">                              PROT_READ | PROT_WRITE /* required */,  </span><br><span class="line">                              MAP_SHARED /* recommended */,  </span><br><span class="line">                              fd, buf.m.offset);  </span><br><span class="line">  </span><br><span class="line">                if (MAP_FAILED == buffers[n_buffers].start)  </span><br><span class="line">                        errno_exit(&quot;mmap&quot;);  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">static void init_userp(unsigned int buffer_size)  </span><br><span class="line">&#123;  </span><br><span class="line">        struct v4l2_requestbuffers req;  </span><br><span class="line">  </span><br><span class="line">        CLEAR(req);  </span><br><span class="line">  </span><br><span class="line">        req.count  = 4;  </span><br><span class="line">        req.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">        req.memory = V4L2_MEMORY_USERPTR;  </span><br><span class="line">  </span><br><span class="line">        if (-1 == xioctl(fd, VIDIOC_REQBUFS, &amp;req)) &#123;  </span><br><span class="line">                if (EINVAL == errno) &#123;  </span><br><span class="line">                        fprintf(stderr, &quot;%s does not support &quot;  </span><br><span class="line">                                 &quot;user pointer i/o\n&quot;, dev_name);  </span><br><span class="line">                        exit(EXIT_FAILURE);  </span><br><span class="line">                &#125; else &#123;  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_REQBUFS&quot;);  </span><br><span class="line">                &#125;  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        buffers = calloc(4, sizeof(*buffers));  </span><br><span class="line">  </span><br><span class="line">        if (!buffers) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;Out of memory\n&quot;);  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        for (n_buffers = 0; n_buffers &lt; 4; ++n_buffers) &#123;  </span><br><span class="line">                buffers[n_buffers].length = buffer_size;  </span><br><span class="line">                buffers[n_buffers].start = malloc(buffer_size);  </span><br><span class="line">  </span><br><span class="line">                if (!buffers[n_buffers].start) &#123;  </span><br><span class="line">                        fprintf(stderr, &quot;Out of memory\n&quot;);  </span><br><span class="line">                        exit(EXIT_FAILURE);  </span><br><span class="line">                &#125;  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">/* five operations </span><br><span class="line"> * step1 : cap :query camera&apos;s capability and check it(is a video device? is it support read? is it support streaming?) </span><br><span class="line"> * step2 : cropcap:set cropcap&apos;s type and get cropcap by VIDIOC_CROPCAP </span><br><span class="line"> * step3 : set crop parameter by VIDIOC_S_CROP (such as frame type and angle) </span><br><span class="line"> * step4 : set fmt </span><br><span class="line"> * step5 : mmap </span><br><span class="line"> */  </span><br><span class="line">static void init_device(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        struct v4l2_capability cap;  </span><br><span class="line">        struct v4l2_cropcap cropcap;  </span><br><span class="line">        struct v4l2_crop crop;  </span><br><span class="line">        struct v4l2_format fmt;  </span><br><span class="line">        unsigned int min;  </span><br><span class="line">  </span><br><span class="line">        if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &amp;cap)) &#123;  </span><br><span class="line">                if (EINVAL == errno) &#123;  </span><br><span class="line">                        fprintf(stderr, &quot;%s is no V4L2 device\n&quot;,  </span><br><span class="line">                                 dev_name);  </span><br><span class="line">                        exit(EXIT_FAILURE);  </span><br><span class="line">                &#125; else &#123;  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_QUERYCAP&quot;);  </span><br><span class="line">                &#125;  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        if (!(cap.capabilities &amp; V4L2_CAP_VIDEO_CAPTURE)) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;%s is no video capture device\n&quot;,  </span><br><span class="line">                         dev_name);  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        switch (io) &#123;  </span><br><span class="line">        case IO_METHOD_READ:  </span><br><span class="line">                if (!(cap.capabilities &amp; V4L2_CAP_READWRITE)) &#123;  </span><br><span class="line">                        fprintf(stderr, &quot;%s does not support read i/o\n&quot;,  </span><br><span class="line">                                 dev_name);  </span><br><span class="line">                        exit(EXIT_FAILURE);  </span><br><span class="line">                &#125;  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_MMAP:  </span><br><span class="line">        case IO_METHOD_USERPTR:  </span><br><span class="line">                if (!(cap.capabilities &amp; V4L2_CAP_STREAMING)) &#123;  </span><br><span class="line">                        fprintf(stderr, &quot;%s does not support streaming i/o\n&quot;,  </span><br><span class="line">                                 dev_name);  </span><br><span class="line">                        exit(EXIT_FAILURE);  </span><br><span class="line">                &#125;  </span><br><span class="line">                break;  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">        /* Select video input, video standard and tune here. */  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">        CLEAR(cropcap);  </span><br><span class="line">  </span><br><span class="line">        cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">        /* if device support cropcap&apos;s type then set crop */  </span><br><span class="line">        if (0 == xioctl(fd, VIDIOC_CROPCAP, &amp;cropcap)) &#123;  </span><br><span class="line">                crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">                crop.c = cropcap.defrect; /* reset to default */  </span><br><span class="line">  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_S_CROP, &amp;crop)) &#123;  </span><br><span class="line">                        switch (errno) &#123;  </span><br><span class="line">                        case EINVAL:  </span><br><span class="line">                                /* Cropping not supported. */  </span><br><span class="line">                                break;  </span><br><span class="line">                        default:  </span><br><span class="line">                                /* Errors ignored. */  </span><br><span class="line">                                break;  </span><br><span class="line">                        &#125;  </span><br><span class="line">                &#125;  </span><br><span class="line">        &#125; else &#123;  </span><br><span class="line">                /* Errors ignored. */  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">        CLEAR(fmt);  </span><br><span class="line">  </span><br><span class="line">        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  </span><br><span class="line">        if (force_format) &#123;  </span><br><span class="line">                fmt.fmt.pix.width       = 640;  </span><br><span class="line">                fmt.fmt.pix.height      = 480;  </span><br><span class="line">                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;  </span><br><span class="line">                fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;  </span><br><span class="line">  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_S_FMT, &amp;fmt))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_S_FMT&quot;);  </span><br><span class="line">  </span><br><span class="line">                /* Note VIDIOC_S_FMT may change width and height. */  </span><br><span class="line">        &#125; else &#123;  </span><br><span class="line">                /* Preserve original settings as set by v4l2-ctl for example */  </span><br><span class="line">                if (-1 == xioctl(fd, VIDIOC_G_FMT, &amp;fmt))  </span><br><span class="line">                        errno_exit(&quot;VIDIOC_G_FMT&quot;);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        /* Buggy driver paranoia. */  </span><br><span class="line">        min = fmt.fmt.pix.width * 2;  </span><br><span class="line">        if (fmt.fmt.pix.bytesperline &lt; min)  </span><br><span class="line">                fmt.fmt.pix.bytesperline = min;  </span><br><span class="line">        min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;  </span><br><span class="line">        if (fmt.fmt.pix.sizeimage &lt; min)  </span><br><span class="line">                fmt.fmt.pix.sizeimage = min;  </span><br><span class="line">  </span><br><span class="line">        switch (io) &#123;  </span><br><span class="line">        case IO_METHOD_READ:  </span><br><span class="line">                init_read(fmt.fmt.pix.sizeimage);  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_MMAP:  </span><br><span class="line">                init_mmap();  </span><br><span class="line">                break;  </span><br><span class="line">  </span><br><span class="line">        case IO_METHOD_USERPTR:  </span><br><span class="line">                init_userp(fmt.fmt.pix.sizeimage);  </span><br><span class="line">                break;  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">/* </span><br><span class="line"> * close (fd) </span><br><span class="line"> */  </span><br><span class="line">static void close_device(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        if (-1 == close(fd))  </span><br><span class="line">                errno_exit(&quot;close&quot;);  </span><br><span class="line">  </span><br><span class="line">        fd = -1;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">/* three operations </span><br><span class="line"> * step 1 : check dev_name and st_mode </span><br><span class="line"> * step 2 : open(device) </span><br><span class="line"> */  </span><br><span class="line">static void open_device(void)  </span><br><span class="line">&#123;  </span><br><span class="line">        struct stat st;  </span><br><span class="line">  </span><br><span class="line">        if (-1 == stat(dev_name, &amp;st)) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;Cannot identify &apos;%s&apos;: %d, %s\n&quot;,  </span><br><span class="line">                         dev_name, errno, strerror(errno));  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        if (!S_ISCHR(st.st_mode)) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;%s is no device\n&quot;, dev_name);  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);  </span><br><span class="line">  </span><br><span class="line">        if (-1 == fd) &#123;  </span><br><span class="line">                fprintf(stderr, &quot;Cannot open &apos;%s&apos;: %d, %s\n&quot;,  </span><br><span class="line">                         dev_name, errno, strerror(errno));  </span><br><span class="line">                exit(EXIT_FAILURE);  </span><br><span class="line">        &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">static void usage(FILE *fp, int argc, char **argv)  </span><br><span class="line">&#123;  </span><br><span class="line">        fprintf(fp,  </span><br><span class="line">                 &quot;Usage: %s [options]\n\n&quot;  </span><br><span class="line">                 &quot;Version 1.3\n&quot;  </span><br><span class="line">                 &quot;Options:\n&quot;  </span><br><span class="line">                 &quot;-d | --device name   Video device name [%s]\n&quot;  </span><br><span class="line">                 &quot;-h | --help          Print this message\n&quot;  </span><br><span class="line">                 &quot;-m | --mmap          Use memory mapped buffers [default]\n&quot;  </span><br><span class="line">                 &quot;-r | --read          Use read() calls\n&quot;  </span><br><span class="line">                 &quot;-u | --userp         Use application allocated buffers\n&quot;  </span><br><span class="line">                 &quot;-o | --output        Outputs stream to stdout\n&quot;  </span><br><span class="line">                 &quot;-f | --format        Force format to 640x480 YUYV\n&quot;  </span><br><span class="line">                 &quot;-c | --count         Number of frames to grab [%i]\n&quot;  </span><br><span class="line">                 &quot;&quot;,  </span><br><span class="line">                 argv[0], dev_name, frame_count);  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line">static const char short_options[] = &quot;d:hmruofc:&quot;;  </span><br><span class="line">  </span><br><span class="line">static const struct option  </span><br><span class="line">long_options[] = &#123;  </span><br><span class="line">        &#123; &quot;device&quot;, required_argument, NULL, &apos;d&apos; &#125;,  </span><br><span class="line">        &#123; &quot;help&quot;,   no_argument,       NULL, &apos;h&apos; &#125;,  </span><br><span class="line">        &#123; &quot;mmap&quot;,   no_argument,       NULL, &apos;m&apos; &#125;,  </span><br><span class="line">        &#123; &quot;read&quot;,   no_argument,       NULL, &apos;r&apos; &#125;,  </span><br><span class="line">        &#123; &quot;userp&quot;,  no_argument,       NULL, &apos;u&apos; &#125;,  </span><br><span class="line">        &#123; &quot;output&quot;, no_argument,       NULL, &apos;o&apos; &#125;,  </span><br><span class="line">        &#123; &quot;format&quot;, no_argument,       NULL, &apos;f&apos; &#125;,  </span><br><span class="line">        &#123; &quot;count&quot;,  required_argument, NULL, &apos;c&apos; &#125;,  </span><br><span class="line">        &#123; 0, 0, 0, 0 &#125;  </span><br><span class="line">&#125;;  </span><br><span class="line">  </span><br><span class="line">int main(int argc, char **argv)  </span><br><span class="line">&#123;  </span><br><span class="line">        dev_name = &quot;/dev/video4&quot;;  </span><br><span class="line">  </span><br><span class="line">        for (;;) &#123;  </span><br><span class="line">                int idx;  </span><br><span class="line">                int c;  </span><br><span class="line">  </span><br><span class="line">                c = getopt_long(argc, argv,  </span><br><span class="line">                                short_options, long_options, &amp;idx);  </span><br><span class="line">  </span><br><span class="line">                if (-1 == c)  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                switch (c) &#123;  </span><br><span class="line">                case 0: /* getopt_long() flag */  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                case &apos;d&apos;:  </span><br><span class="line">                        dev_name = optarg;  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                case &apos;h&apos;:  </span><br><span class="line">                        usage(stdout, argc, argv);  </span><br><span class="line">                        exit(EXIT_SUCCESS);  </span><br><span class="line">  </span><br><span class="line">                case &apos;m&apos;:  </span><br><span class="line">                        io = IO_METHOD_MMAP;  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                case &apos;r&apos;:  </span><br><span class="line">                        io = IO_METHOD_READ;  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                case &apos;u&apos;:  </span><br><span class="line">                        io = IO_METHOD_USERPTR;  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                case &apos;o&apos;:  </span><br><span class="line">                        out_buf++;  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                case &apos;f&apos;:  </span><br><span class="line">                        force_format++;  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                case &apos;c&apos;:  </span><br><span class="line">                        errno = 0;  </span><br><span class="line">                        frame_count = strtol(optarg, NULL, 0);  </span><br><span class="line">                        if (errno)  </span><br><span class="line">                                errno_exit(optarg);  </span><br><span class="line">                        break;  </span><br><span class="line">  </span><br><span class="line">                default:  </span><br><span class="line">                        usage(stderr, argc, argv);  </span><br><span class="line">                        exit(EXIT_FAILURE);  </span><br><span class="line">                &#125;  </span><br><span class="line">        &#125;  </span><br><span class="line">  </span><br><span class="line">        open_device();  </span><br><span class="line">        init_device();  </span><br><span class="line">        start_capturing();  </span><br><span class="line">        mainloop();  </span><br><span class="line">        stop_capturing();  </span><br><span class="line">        uninit_device();  </span><br><span class="line">        close_device();  </span><br><span class="line">        fprintf(stderr, &quot;\n&quot;);  </span><br><span class="line">        return 0;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>参考：<br><a href="https://blog.csdn.net/u010164190/article/details/53189836" target="_blank" rel="noopener">https://blog.csdn.net/u010164190/article/details/53189836</a></p>
<p><a href="https://blog.csdn.net/qq_38880380/article/details/78261995" target="_blank" rel="noopener">https://blog.csdn.net/qq_38880380/article/details/78261995</a></p>


                
            </div>

            <!-- Comments -->
            
                <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                    


                </div>
            
        </div>
    </div>
</article>

    <!-- Footer -->
    <hr>

<!-- Footer -->
<footer>
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <ul class="list-inline text-center">
                    

                    

                    
                        <li>
                            <a href="https://github.com/klugjo/hexo-theme-clean-blog" target="_blank">
                                <span class="fa-stack fa-lg">
                                    <i class="fa fa-circle fa-stack-2x"></i>
                                    <i class="fa fa-github fa-stack-1x fa-inverse"></i>
                                </span>
                            </a>
                        </li>
                    

                    

                    

                    
                </ul>
                <p class="copyright text-muted">&copy; 2020 Cyrus<br></p>
                <p class="copyright text-muted">Original Theme <a target="_blank" href="http://startbootstrap.com/template-overviews/clean-blog/">Clean Blog</a> from <a href="http://startbootstrap.com/" target="_blank">Start Bootstrap</a></p>
                <p class="copyright text-muted">Adapted for <a target="_blank" href="https://hexo.io/">Hexo</a> by <a href="http://www.codeblocq.com/" target="_blank">Jonathan Klughertz</a></p>
                <p class="copyright text-muted"><a href="http://www.beian.miit.gov.cn">粤ICP备18110122号-1</a></p>
            </div>
        </div>
    </div>
</footer>


    <!-- After footer scripts -->
    
<!-- jQuery -->
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>

<!-- Bootstrap -->
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>

<!-- Gallery -->
<script src="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.js" type="text/javascript" charset="utf-8"></script>

<!-- Disqus Comments -->



</body>

</html>